﻿using BeetleX.XRPC.Clients;
using System;
using System.Threading.Tasks;

#nullable disable
namespace BeetleX.XRPC
{
    internal class ServerDelegateHandler : DelegateHandler
    {
        public ServerDelegateHandler(Type type)
          : base(type)
        {
        }

        public ISession Session { get; set; }

        public XRPCServer Server { get; set; }

        public Delegate SessionDelegateProxy { get; set; }

        protected override Task OnVoidExecute(params object[] data)
        {
            this.Server.Send(new RPCPacket()
            {
                NeedReply = false,
                Url = "/__delegate/" + this.Name,
                Data = data
            }, new ISession[1] { this.Session });
            return Task.CompletedTask;
        }

        protected override async Task<T> OnTaskExecute<T>(params object[] data)
        {
            ServerDelegateHandler serverDelegateHandler = this;
            bool istask = typeof(T) == typeof(RESULT_NULL);
            using RPCPacket request = new RPCPacket();
            request.NeedReply = true;
            request.Url = "/__delegate/" + serverDelegateHandler.Name;
            request.Data = data;
            Type[] returnTypes = serverDelegateHandler.GetReturnTypes();
            RPCPacket rpcPacket = await serverDelegateHandler.Server.SendWait(request, serverDelegateHandler.Session, returnTypes);
            if (rpcPacket.Status != 200)
                throw new XRPCException((string)rpcPacket.Data[0]);

            if (istask)
                return (T)(object)new RESULT_NULL();
            return (T)rpcPacket.Data[0];
        }

        public void Bind(ISession session, XRPCServer server)
        {
            this.Session = session;
            this.Server = server;
            this.SessionDelegateProxy = this.CreateDelegate();
        }
    }
}
